﻿using System;

namespace Flagwind.Data
{
	internal class PropertyAccessor<T, P> : INamedMemberAccessor
	{
		private Func<T, P> GetValueDelegate;
		private Action<T, P> SetValueDelegate;
		private Type memberType;

		public PropertyAccessor(Type type, string propertyName)
		{
			var propertyInfo = type.GetProperty(propertyName);
			if(propertyInfo != null)
			{
				if(propertyInfo.CanRead)
				{
					GetValueDelegate = (Func<T, P>)Delegate.CreateDelegate(typeof(Func<T, P>), propertyInfo.GetGetMethod());
				}
				if(propertyInfo.CanWrite)
				{
					SetValueDelegate = (Action<T, P>)Delegate.CreateDelegate(typeof(Action<T, P>), propertyInfo.GetSetMethod());
				}
			}
			this.memberType = propertyInfo.PropertyType;
		}

		public object GetValue(object instance)
		{
			if(GetValueDelegate != null)
			{
				return GetValueDelegate((T)instance);
			}
			else
			{
				return null;
			}
		}

		public void SetValue(object instance, object newValue)
		{
			if(SetValueDelegate != null)
			{
				SetValueDelegate((T)instance, (P)newValue);
			}
		}

		public Type MemberType
		{
			get
			{
				return this.memberType;
			}
		}
	}
}